var ojsc = function () {
	var regExp = /^on/i,
		regExpLink = /^javascript:/i,
		regExpClasses = /ojsc\-(inline\-event|javascript\-link)/gi,
		regExpSpaceMatch = /^\s+.*\s+$/,
		regExpSpaceReplace = /(\s+).+/,
		regExpSpaceFix = /^\s+|\s+$/g,
		classReplace = function (match) {
			var retVal = "";
			if (regExpSpaceMatch.test(match)) {
				retVal = match.replace(regExpSpaceReplace, "$1");
			}
			return retVal;
		},
		styles = [
			"position : fixed",
			"display : none",
			"min-width : 300px",
			"font : 12px Helvetica, Verdana, Arial, sans-serif",
			"color : #fff",
			"background : #333",
			"text-align: left",
			"padding : 10px",
			"z-index : 1000",
			"opacity : 0.9",
			"-moz-border-radius : 5px"
		],
		reportStyles = [
			"display : block",
			"width : 200px",
			"left : 0",
			"bottom : 0"
		],
		innerStyles = [
			"font : 12px Helvetica, Verdana, Arial, sans-serif",
			"color : #fff",
			"margin: 0 0 10px 0;"
		],
		inlineEvents = {
			items : 0
		},
		javascriptLinks = {
			items : 0
		},
		inlineEventElmStyle = [
			"border : 2px solid red"
		],		
		javascriptLinksElmStyle = [
			"border : 2px solid magenta"
		],
		states = {
			
		},
		attribute,
		attrName,
		statusBarButton;
	return {
		init : function () {
			statusBarButton = document.getElementById("ojsc-status-bar");
			gBrowser.tabContainer.addEventListener("TabSelect", function () {
				ojsc.setStatusBar.apply(ojsc, arguments);
			}, false);
			gBrowser.addEventListener("load", function () {
				ojsc.clearState.apply(ojsc, arguments);
			}, false);
		},
		
		getTabIndex : function () {
			var browsers = gBrowser.browsers,
				tabIndex;
			for (var i=0, il=browsers.length, browser; i<il; i++) {
				if(gBrowser.getBrowserAtIndex(i).contentWindow === content) {
					tabIndex = i;
					break;
				}
			}
			return tabIndex;
		},
		
		getState : function () {
			var tabIndex = this.getTabIndex(),
				state = states[tabIndex];
			return state;	
		},
		
		clearState : function () {
			var state = this.getState();
			this.clearAll();
			state.hasRun = false;
			this.setStatusBar();
		},
		
		setStatusBar : function () {
			var state = this.getState(),
				statusIcon = "chrome://ojsc/skin/",
				statusText;
				
			if(state && state.hasRun) {
				statusIcon += "status-bar.png";
				statusText = "Hide Obtrusive JavaScript Checker";
			}
			else {
				statusIcon += "status-bar-disabled.png";
				statusText = "Run Obtrusive JavaScript Checker";
			}
			statusBarButton.setAttribute("src", statusIcon);
			statusBarButton.setAttribute("tooltiptext", statusText);
		},
			
		run : function () {
			var state = this.getState(),
				tabIndex = this.getTabIndex();
			if(!state) {
				state = states[tabIndex] = {
					hasRun : false,
					affectedElms : []
				};
			}
			this.clearAll();
			
			if (state.hasRun) {
				state.hasRun = false;
				this.setStatusBar();
				return;
			}
			else {
				state.hasRun = true;
				this.setStatusBar();
			}
			
			
			var affectedElms = state.affectedElms;
			
			// Needed to be here to make sure HTML elements are retrieved from the active tab
			var allElms = content.document.body.getElementsByTagName("*");
			this.setStatusBar();
			
			// Creation of custom style sheet
			var styleSheet = content.document.createElement("style");
			styleSheet.id = "ojsc-style";
			styleSheet.type = "text/css";
			styleSheet.rel = "stylesheet";
			styleSheet.href = "http://sites/test/test.css";
			content.document.getElementsByTagName("head")[0].appendChild(styleSheet);
			
			// Append CSS rules to it
			var docStyleSheets = content.document.styleSheets,
				lastStyleSheet = docStyleSheets.length - 1;
			docStyleSheets[lastStyleSheet].insertRule(("div.ojsc-overlay {" + styles.join(";\n") + "}"), 0);
			docStyleSheets[lastStyleSheet].insertRule(("div.ojsc-overlay-report {" + reportStyles.join(";\n") + "}"), 1);
			docStyleSheets[lastStyleSheet].insertRule(("div.ojsc-overlay p {" + innerStyles.join(";\n") + "}"), 2);
			docStyleSheets[lastStyleSheet].insertRule((".ojsc-inline-event {" + inlineEventElmStyle.join(";\n") + "}"), 3);
			docStyleSheets[lastStyleSheet].insertRule((".ojsc-javascript-link {" + javascriptLinksElmStyle.join(";\n") + "}"), 4);
			
			var viewer,
				report,
				elm, 
				attributes, 
				attr,
				item,
				eventHandler;

			viewer = content.document.createElement("div");
			viewer.id = "ojsc-viewer";
			viewer.className = "ojsc-overlay";
			content.document.body.appendChild(viewer);
						
			for (var i=0, il=allElms.length; i<il; i++) {
				elm = allElms[i];
				if (elm.nodeType === 1) {
					attributes = elm.attributes;
					for (var j=0, jl=attributes.length; j<jl; j++) {
						attribute = attributes[j];
						attrName = attribute.name;
						if(regExp.test(attrName)){
							elm.className += ((elm.className.length > 0)? " " : "") + "ojsc-inline-event";
							inlineEvents.items += 1;
							if (typeof inlineEvents[attrName] === "number") {
								inlineEvents[attrName] += 1;
							}
							else {
								inlineEvents[attrName] = 1;
							}
							elm.addEventListener("mouseover", this.showInfo, false);
							elm.addEventListener("mouseout", this.hideInfo, false);
							affectedElms.push(elm);
						}
						else if (attrName === "href" && regExpLink.test(attribute.value)) {
							javascriptLinks.items += 1;
							elm.className += ((elm.className.length > 0)? " " : "") + "ojsc-javascript-link";
							elm.addEventListener("mouseover", this.showJavaScriptLinkInfo, false);
							elm.addEventListener("mouseout", this.hideInfo, false);
							affectedElms.push(elm);
						}
					}
				}
			}
			
			report = content.document.createElement("div");
			report.id = "ojsc-report";
			report.className = "ojsc-overlay ojsc-overlay-report";
			report.innerHTML = "<p><b>Number of javascript: links:</b> " + javascriptLinks.items + "</p>";
			report.innerHTML += "<p><b>Number of inline events:</b> " + inlineEvents.items + "</p>";
			for (eventHandler in inlineEvents) {
				if (eventHandler !== "items") {
					report.innerHTML += "<p style='margin-left: 20px'>" + eventHandler + ": " + inlineEvents[eventHandler] + "</p>";
				}
			}
			content.document.body.appendChild(report);
		},	

		showInfo : function (evt) {
			var viewer = content.document.getElementById("ojsc-viewer");
			var attributes = this.attributes,
				events = [],
				eventElm;
			for (var i=0, il=attributes.length; i<il; i++) {
				attribute = attributes[i];
				attrName = attribute.name;
				if(regExp.test(attrName)){
					events.push(attrName + ": " + attribute.value);
				}
			}
			viewer.innerHTML = "";
			for (var j=0, jl=events.length; j<jl; j++) {
				eventElm = content.document.createElement("p");
				eventElm.innerHTML = events[j];
				viewer.appendChild(eventElm);
			}
			ojsc.positionAndShow(evt);
			evt.stopPropagation();
		},
		
		showJavaScriptLinkInfo : function (evt) {
			var viewer = content.document.getElementById("ojsc-viewer");
			viewer.innerHTML = "";
			var eventElm = content.document.createElement("p");
			eventElm.innerHTML = "href: " + this.getAttribute("href");
			viewer.appendChild(eventElm);
			ojsc.positionAndShow(evt);
			evt.stopPropagation();
		},
		
		positionAndShow : function (evt) {
			var viewer = content.document.getElementById("ojsc-viewer");
			viewer.style.left = (evt.clientX + 10 + window.pageXOffset) + "px";	
			viewer.style.top = (evt.clientY + 10 + window.pageYOffset) + "px";
			viewer.style.display = "block";
		},
		
		hideInfo : function () {
			var viewer = content.document.getElementById("ojsc-viewer");
			if (viewer) {
				viewer.style.display = "none";
			}
		},
		
		clear : function () {
			var styles = content.document.getElementById("ojsc-style");
			if (styles) {
				styles.parentNode.removeChild(styles);
			}
			var viewer = content.document.getElementById("ojsc-viewer");
			if (viewer && viewer.parentNode) {
				viewer.parentNode.removeChild(viewer);
			}
			var report = content.document.getElementById("ojsc-report");
			if (report && report.parentNode) {
				report.parentNode.removeChild(report);
			}
			inlineEvents = {
				items : 0
			};
			javascriptLinks = {
				items : 0
			};
		},
		
		clearAll : function () {
			var state = this.getState(),
				affectedElms = state.affectedElms;
			this.clear();
			for (var i=0, il=affectedElms.length, elm; i<il; i++) {
				elm = affectedElms[i];
				elm.className = elm.className.replace(regExpClasses, classReplace).replace(regExpSpaceFix, "");
				elm.removeEventListener("mouseover", this.showInfo, false);
				elm.removeEventListener("mouseover", this.showJavaScriptLinkInfo, false);
				elm.removeEventListener("mouseout", this.hideInfo, false);
			}
			state.affectedElms = [];
		}
	};
}();

ojscWrapper = {
	onMenuItemCommand : function (evt) {
		ojsc.run();
	},
	
	onContextMenuItemCommand : function (evt) {
		ojsc.run();
	},
	
	onStatusbarButtonCommand : function (evt) {
		ojsc.run();
	},
	
	onToolbarButtonCommand : function (evt) {
		ojsc.run();
	}
};

window.addEventListener("load", function () {
	ojsc.init.apply(ojsc, arguments);
}, false);